<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!--[if lt IE 9]>
  <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<![endif]-->
<title>VIM 中文用户手册: 折叠</title>
<link rel="stylesheet" href="vim-stylesheet.css" type="text/css" />
<link rel="canonical" href="https://yianwillis.github.io/vimcdoc/doc/usr_28.html" />
<script type="text/javascript" src="vimcdoc.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<nav id=banner>
<form action=tags.html target="tag_iframe">
  <input type="text" name="tag" id="tag" placeholder="标签搜索">
</form>
<iframe name="tag_iframe" src=""></iframe>
<a href="help.html">帮助总览</a> &middot;
<hr/>
<a href="quickref.html">快速参考</a> &middot;
<a href="index.html">命令索引</a> &middot;
<a href="eval.html#functions">函数列表</a> &middot;
<a href="quickref.html#option-list">选项列表</a> &middot;
<hr/>
<a href="usr_toc.html">用户手册</a> &middot;
<a href="help.html#reference_toc">参考手册</a> &middot;
</nav>

<header>
<h2>usr_28</h2>
</header>
<article id=outer>
<section class=inner>
<b class="vimtag"> <a name="usr_28.txt">usr_28.txt</a> </b>    适用于 Vim 9.0 版本。   最近更新: 2013年8月

                     <code class="vim">VIM 用户手册 - by Bram Moolenaar</code>
                                <code class="vim">译者</code>: Chimin Yen

                                   折叠


结构化的文本可以分为许多节。而一节之内可以再分小节。折叠允许你将一节显示为一
行，并提供文本的概览。本章将解释各种实现折叠的方法。

 <a href="usr_28.html#28.1">28.1</a>   什么是折叠？
 <a href="usr_28.html#28.2">28.2</a>   手动折叠
 <a href="usr_28.html#28.3">28.3</a>   对折叠的操作
 <a href="usr_28.html#28.4">28.4</a>   存储和恢复折叠
 <a href="usr_28.html#28.5">28.5</a>   依缩进折叠
 <a href="usr_28.html#28.6">28.6</a>   依标志折叠
 <a href="usr_28.html#28.7">28.7</a>   依语法折叠
 <a href="usr_28.html#28.8">28.8</a>   依表达式折叠
 <a href="usr_28.html#28.9">28.9</a>   折叠未被改动的行
 <a href="usr_28.html#28.10">28.10</a>  使用哪种折叠办法呢？

        下一章:  <a href="usr_29.html#usr_29.txt">usr_29.txt</a>   在代码间移动
        前一章:  <a href="usr_27.html#usr_27.txt">usr_27.txt</a>   查找命令及模式
          目录:  <a href="usr_toc.html#usr_toc.txt">usr_toc.txt</a> 

</section><hr class="doubleline" /><section class=inner>
<h4><b class="vimtag"> <a name="28.1">28.1</a> </b>  什么是折叠？</h4>
折叠用于把缓冲区内某一范围内的文本行显示为屏幕上的一行。就像一张纸，要它缩短
些，可以把它折叠起来:

        +------------------------+
        | 行 1           |
        | 行 2           |
        | 行 3           |
        |_______________________ |
        \                        \
         \________________________\
         / 被折叠的行             /
        /________________________/
        | 行 12          |
        | 行 13          |
        | 行 14          |
        +------------------------+

那些文本仍然在缓冲区内而没有改变。受到折叠影响的只是文本行显示的方式。

折叠的好处是，通过把多行的一节折叠成带有折叠提示的一行，会使你更好地了解对文本
的宏观结构。

</section><hr class="doubleline" /><section class=inner>
<h4><b class="vimtag"> <a name="28.2">28.2</a> </b>  手动折叠</h4>
试一试: 把光标置于某一段落内，并键入: 
<code class="example"></code>
<code class="example">        zfap</code>
<code class="example"></code>
你将会看到该段落被一行高亮的文本所代替。你已经创建了一个折叠了。 <a href="fold.html#zf">zf</a>  是个操作
符，而  <a href="motion.html#ap">ap</a>  是一个文本对象。你可以将  <a href="fold.html#zf">zf</a>  操作符跟任何一个移动命令联用，为所经
之处的文本创建一个折叠。 <a href="fold.html#zf">zf</a>  也能在可视模式下使用。

若要再阅读那些文本，可以键入以下命令以打开该折叠: 
<code class="example"></code>
<code class="example">        zo</code>
<code class="example"></code>
你还可以用以下命令再关闭该折叠: 
<code class="example"></code>
<code class="example">        zc</code>
<code class="example"></code>
所有的折叠命令都以 'z' 开头。展开你的想像力，这个字母看起来就像一张折叠起来的
纸的侧面。而 "z" 后面可用的字母，由于采用了帮助记忆方法选择，很容易记得住:

        zf      F-old creation (创建折叠)
        zo      O-pen a fold (打开折叠)
        zc      C-lose a fold (关闭折叠)

折叠可以嵌套: 一个含有折叠的文本区可以被再次折叠。例如，你可以折叠本节内每一段
落，然后折叠本章内所有的节。试试看。你将<code class="note">注意</code>到，打开全章的折叠，会将节的折叠还
原得跟以前一样，有些打开，而有些关闭。

假定你已经创建了若干折叠，而现在需要阅览全部文本。你可以移到每个折叠处，并键入
"zo"。若要做得更快，可以用这个命令: 
<code class="example"></code>
<code class="example">        zr</code>
<code class="example"></code>
这将减少 (R-educe) 折叠。相反的操作是: 
<code class="example"></code>
<code class="example">        zm</code>
<code class="example"></code>
这将折叠更多 (M-ore)。你可以重复 "zr" 和 "zm" 来打开和关闭若干层嵌套的折叠。

如果你有一个嵌套了好几层深的折叠，你可以用这个命令把它们全部打开: 
<code class="example"></code>
<code class="example">        zR</code>
<code class="example"></code>
这将减少折叠直至一个也不剩。而用下面这个命令你可以关闭所有的折叠: 
<code class="example"></code>
<code class="example">        zM</code>
<code class="example"></code>
这将增加折叠，直至所有的折叠都关闭了。

你可以用  <a href="fold.html#zn">zn</a>  命令快速禁止折叠功能。然后  <a href="fold.html#zN">zN</a>  恢复原来的折叠。 <a href="fold.html#zi">zi</a>  切换于两者
之间。以下步骤是一种实用的操作方法:
- 创建折叠，以获取你的文件的概览
- 移动到你要操作的地方
- 执行  <a href="fold.html#zi">zi</a>  以便一边看着文本，一边编辑
- 再执行  <a href="fold.html#zi">zi</a>   以便移动到另一处

在参考手册中有更多关于手动折叠的内容:  <a href="fold.html#fold-manual">fold-manual</a> 

</section><hr class="doubleline" /><section class=inner>
<h4><b class="vimtag"> <a name="28.3">28.3</a> </b>  对折叠的操作</h4>
当一些折叠关闭时，移动命令，如 "j" 和 "k" 会轻松的移过折叠，就像它是单个空行一
样。这允许你快速移过折叠了的文本。

你可以向对待单行一样复制，删除和粘贴折叠。当你要改动某个程序里的函数的先后次序
时，这是很实用的。首先，为 <a href="options.html#'foldmethod'">'foldmethod'</a> 选择一个正确的折叠方法，以保证每个折叠
包含了整个函数 (或稍缺一点儿)。然后，用 "dd" 命令删除该函数，移动光标，并用
"p" 命令粘贴。如果函数中某些行在折叠之上，或之下，你可以利用可视模式下的选择方
法:
- 把光标置于被移文本的首行
- 击 "V" 键开始可视模式
- 把光标置于被移文本的末行
- 击 "d" 键删除被选中的行。
- 把光标移到新位置，并击 "p" 键把文本粘贴在那儿。

有时候，查看或记住一个折叠在哪儿，挺不容易的。更别说用  <a href="fold.html#zo">zo</a>  命令来打开了。要查
看那些已定义的折叠: 
<code class="example"></code>
<code class="example">        :set foldcolumn=4</code>
<code class="example"></code>
这个命令将在窗口左边显示一小栏来标识各个折叠。一个 "+" 表示某个关闭的折叠。一
个 "-" 表示每个打开的折叠的开头，而 "|" 则表示该折叠内其余的行。

你可以在折叠栏内用鼠标点击 "+"，以打开一个折叠。点击 "-" ，或在它之下的某个
"|" ，将关闭一个打开的折叠。

打开所有光标行上的折叠用  <a href="fold.html#zO">zO</a> 。
关闭所有光标行上的折叠用  <a href="fold.html#zC">zC</a> 。
删除一个光标行上的折叠用  <a href="fold.html#zd">zd</a> 。
删除所有光标行上的折叠用  <a href="fold.html#zD">zD</a> 。

当你进入插入模式后，光标行上的折叠永远不会关闭。那是要让你看见你打的什么字！

当光标前后跳转至折叠，或在折叠上左右移动时，折叠就会自动打开。例如，零命令 "0"
打开光标下的折叠 (假设 <a href="options.html#'foldopen'">'foldopen'</a> 包含 "hor"，即默认设置)。<a href="options.html#'foldopen'">'foldopen'</a> 选项可以
修改，为指定的某一类命令打开折叠。如果你要光标遇到折叠，折叠就打开，那么可以这
么做: 
<code class="example"></code>
<code class="example">        :set foldopen=all</code>
<code class="example"></code>
<code class="note">警告</code>: 你将因此无法移到一个关闭的折叠上。你也许只想临时用一用这个命令，然后把它
设回默认值: 
<code class="example"></code>
<code class="example">        :set foldopen&amp;</code>
<code class="example"></code>
你可以在移开折叠时自动关闭折叠: 
<code class="example"></code>
<code class="example">        :set foldclose=all</code>
<code class="example"></code>
这个命令将重新把折叠级别 <a href="options.html#'foldlevel'">'foldlevel'</a> 作用到所有的不含光标的折叠。你必须自己试
试看你会不会喜欢这个设置。用  <a href="fold.html#zm">zm</a>  增加折叠级别，并用  <a href="fold.html#zr">zr</a>  减少折叠级别 (减少折
叠的层次)。

折叠是限于本地窗口的。这允许你为同一缓冲区打开两个窗口，一个带折叠，而另一个不
带折叠。或者，一个让所有的折叠关闭，而另一个则让所有的折叠打开。

</section><hr class="doubleline" /><section class=inner>
<h4><b class="vimtag"> <a name="28.4">28.4</a> </b>  存储和恢复折叠</h4>
当你放弃一个文件时 (开始编辑另一个)，其折叠状态就丢失了。如果你稍后再回来编辑
同一文件，那么，所有手动打开和关闭的折叠，全都恢复到它们的默认状态了。如果折叠
是用手动方式创建的，则所有的折叠都消失了！为了保存折叠，可以用  <a href="starting.html#:mkview">:mkview</a>  命
令: 
<code class="example"></code>
<code class="example">        :mkview</code>
<code class="example"></code>
这将储存那些影响文件视图的设定及其它内容。你可以利用 <a href="options.html#'viewoptions'">'viewoptions'</a> 选项修改储
存的范围。当你稍后回到同一文件时，你可以重新载入这个视图: 
<code class="example"></code>
<code class="example">        :loadview</code>
<code class="example"></code>
你可以为一个文件储存多至十个视图。例如，把当前设置储存为第三个视图，并载入第
二个视图: 
<code class="example"></code>
<code class="example">        :mkview 3</code>
<code class="example">        :loadview 2</code>

<code class="note">注意</code> 当你插入或删除一些文本行时，视图可能变得无效。还得检查 <a href="options.html#'viewdir'">'viewdir'</a> 选项，它
指定视图文件储存在哪儿。你可能时不时需要删除旧的视图文件。

</section><hr class="doubleline" /><section class=inner>
<h4><b class="vimtag"> <a name="28.5">28.5</a> </b>  依缩进折叠</h4>
使用  <a href="fold.html#zf">zf</a>  来定义一个折叠很费事。如果你的文本依循一种结构，以较多的缩进表示较低
的层次，那么，你可以采用缩进折叠的方法。这将为每一系列有相同缩进的行创建一个折
叠。缩进较多的行将成为嵌套的折叠。缩进折叠适用于许多编程语言。

我们来试试这个方法。先设定 <a href="options.html#'foldmethod'">'foldmethod'</a> 选项: 
<code class="example"></code>
<code class="example">        :set foldmethod=indent</code>
<code class="example"></code>
然后你可以用  <a href="fold.html#zm">zm</a>  和  <a href="fold.html#zr">zr</a>  命令增加和减少折叠。在下面这个例文上很容易看明白:

本行没有缩进
        本行被缩进一次
                本行被缩进两次
                本行被缩进两次
        本行被缩进一次
本行没有缩进
        本行被缩进一次
        本行被缩进一次

<code class="note">注意</code> 缩进多少和折叠深度之间的关系倚赖于 <a href="options.html#'shiftwidth'">'shiftwidth'</a> 选项。每个 <a href="options.html#'shiftwidth'">'shiftwidth'</a>
选项规定的缩进宽度，在折叠深度上加一。这被称为一个折叠级别。

当你使用  <a href="fold.html#zr">zr</a>  和  <a href="fold.html#zm">zm</a>  命令时，你实际上是在增加或减少 <a href="options.html#'foldlevel'">'foldlevel'</a> 选项。你也可
以直接设置它: 
<code class="example"></code>
<code class="example">        :set foldlevel=3</code>
<code class="example"></code>
这意味着，所有缩进等于或大于 <a href="options.html#'shiftwidth'">'shiftwidth'</a> 三倍的折叠将被关闭。折叠级别设定得越
低，越多的折叠将被关闭。当 <a href="options.html#'foldlevel'">'foldlevel'</a> 为零时，所有的折叠都将被关闭。 <a href="fold.html#zM">zM</a>  把
<a href="options.html#'foldlevel'">'foldlevel'</a> 设为零。相反的命令  <a href="fold.html#zR">zR</a>  把 <a href="options.html#'foldlevel'">'foldlevel'</a> 设为文件中最深的折叠级别。

因此，有两种方法开启和关闭折叠:
(A) 设定折叠级别。
    这提供了一种极快的 "缩小" 方法来查看文本结构，移动光标，以及重新 "放大" 到
    具体的文本。

(B) 利用  <a href="fold.html#zo">zo</a>  和  <a href="fold.html#zc">zc</a>  命令打开和关闭指定的折叠。
    这个方法允许你仅仅打开那些你要打开的折叠，而不影响其它的折叠。

这两种方法可以结合起来用: 你可以先用几次  <a href="fold.html#zm">zm</a>  以关闭大多数折叠，然后用  <a href="fold.html#zo">zo</a> 
打开一个指定的折叠。或者，用  <a href="fold.html#zR">zR</a>  打开所有的折叠，然后用  <a href="fold.html#zc">zc</a>  关闭指定的折叠。

但是，当折叠方法 <a href="options.html#'foldmethod'">'foldmethod'</a> 的值为 "indent" 时，你不能手动定义折叠。因为那样
会引起缩进宽度和折叠级别之间的冲突。

在参考手册中有更多关于缩进折叠的内容:  <a href="fold.html#fold-indent">fold-indent</a> 

</section><hr class="doubleline" /><section class=inner>
<h4><b class="vimtag"> <a name="28.6">28.6</a> </b>  依标志折叠</h4>
文本中的标志用于指定一个折叠区的起点和终点。标志折叠可以精确地控制一个折叠究竟
包含哪些行文本。缺点是文本需要改动。

试试这个: 
<code class="example"></code>
<code class="example">        :set foldmethod=marker</code>
<code class="example"></code>
以下列 C 程序片段为例:

        /* foobar () {{{ */
        int foobar()
        {
                /* return a value {{{ */
                return 42;
                /* }}} */
        }
        /* }}} */

请<code class="note">注意</code>，折叠行将显示位于标志之前的文字。这正好用来说明该折叠包含了什么。

令人十分困扰的是，当某些文本行移动后，标志不再正确地配对。这种局面可以利用编号
标志来避免。例如:

        /* global variables {{{1 */
        int varA，varB;

        /* functions {{{1 */
        /* funcA() {{{2 */
        void funcA() <code class="special">{}</code>

        /* funcB() {{{2 */
        void funcB() <code class="special">{}</code>
        /* }}}1 */

每一个编号标志表示一个编号指定级别的折叠的开始。这将使任何较高层次的折叠在此结
束。你可以只用编号标志的开始符定义所有的折叠。只有当你要明确地在另一个开始前结
束一个折叠时，你才需要加一个标志停止符。

在参考手册中有更多关于标志折叠的内容:  <a href="fold.html#fold-marker">fold-marker</a> 

</section><hr class="doubleline" /><section class=inner>
<h4><b class="vimtag"> <a name="28.7">28.7</a> </b>  依语法折叠</h4>
Vim 为每一种不同的语言使用一个不同的语法文件。语法文件为文件中各种不同语法项定
义颜色。如果你正用 Vim 在一个支持色彩的终端上阅读本文，你所看见的色彩就是由语
法文件 "help" 定制的。
   在语法文件中，你可以加入一些带有 "fold" 参数的语法项。这些语法项将定义折叠
区。这要求写一个语法文件，把这些项目加入其中。编写这样一个文件是不容易的。但是
一旦写成，所有折叠的创建就变成自动的了。
   在此，我们将假定你正使用一个已经写好的语法文件。这样的话，就没更多解释的必
要了。你可以像以上解释过的那样打开和关闭折叠。编辑文件时折叠会自动创建和删除。

在参考手册中有更多关于语法折叠的内容:  <a href="fold.html#fold-syntax">fold-syntax</a> 

</section><hr class="doubleline" /><section class=inner>
<h4><b class="vimtag"> <a name="28.8">28.8</a> </b>  依表达式折叠</h4>
表达式折叠类似于缩进折叠，但并非利用文本行的缩进，而是调用一个函数来计算一行的
折叠级别。当文本的一部分表明那些行属于同一组时，你可以使用这个方法。一个例子是
电子邮件，其中引述的文本由行首的 "&gt;" 来表示。要折叠这些引文，可以用以下命令: 
<code class="example"></code>
<code class="example">        :set foldmethod=expr</code>
<code class="example">        :set foldexpr=strlen(substitute(substitute(getline(v:lnum),'\\s','',\"g\"),'[^&gt;].*','',''))</code>
<code class="example"></code>
你可以在这段文本上试式看:

&gt; quoted text he wrote
&gt; quoted text he wrote
&gt; &gt; double quoted text I wrote
&gt; &gt; double quoted text I wrote

以下是上例中 <a href="options.html#'foldexpr'">'foldexpr'</a> 的解释 (自里至外):
   getline(v:lnum)                      读取当前行
   substitute(...,'\\s','','g')         从当前行删除所有空白字符
   substitute(...,'[^&gt;].*','','')       删除行首那些 '&gt;' 之后的任何字符
   strlen(...)                          计算字符串的长度，即 '&gt;' 的个数

<code class="note">注意</code> 在 ":set" 命令中，每一个空格，双引号和反斜线符之前，必须插入一个反斜杠。
如果这会把你搞糊涂，那么就执行 
<code class="example"></code>
<code class="example">        :set foldexpr</code>
<code class="example"></code>
来检查所产生的实际值。为了修正一个复杂的表达式，请使用命令行补全: 
<code class="example"></code>
<code class="example">        :set foldexpr=&lt;Tab&gt;</code>
<code class="example"></code>
其中 <code class="special">&lt;Tab&gt;</code> 是一个真实的 Tab 键。Vim 将填入以前的值，然后你可以编辑它。

当该表达式变得相对复杂时，你应当将其放入一个函数。然后设定 <a href="options.html#'foldexpr'">'foldexpr'</a> 来调用该
函数。

在参考手册中有更多关于表达式折叠的内容:  <a href="fold.html#fold-expr">fold-expr</a> 

</section><hr class="doubleline" /><section class=inner>
<h4><b class="vimtag"> <a name="28.9">28.9</a> </b>  折叠未被改动的行</h4>
当你在同一窗口也设定 <a href="options.html#'diff'">'diff'</a> 选项时，这种折叠方法就很有用。 <a href="diff.html#vimdiff">vimdiff</a>  命令为你设
定好了使用未改行折叠。例如: 
<code class="example"></code>
<code class="example">        :setlocal diff foldmethod=diff scrollbind nowrap foldlevel=1</code>
<code class="example"></code>
在显示同一文件的不同版本的每个窗口内执行这个命令。你将清楚地看到不同文件间的区
别，因为那些没改动的文本都被折叠起来了。

更多细节参见  <a href="fold.html#fold-diff">fold-diff</a> 。

</section><hr class="doubleline" /><section class=inner>
<h4><b class="vimtag"> <a name="28.10">28.10</a> </b> 使用哪种折叠办法呢？</h4>
所有这些可能性让你感到纳闷，你究竟应该选择哪种方法。不幸的是，没有放之四海皆准
的法则。这里只给出一些提示。

如果存在一个语法文件，其中定义的折叠符合你正在使用的程序语言，那么，语法折叠应
该是最好的选择。否则，你也许得试着写一个。这要求你相当的了解关于查找模式知识。
这并非易事。但一旦写成，你将不必以手动的方式定义折叠了。

键入命令，手动折叠一个个文本区的方法可用于无结构特点的文本。然后用  <a href="starting.html#:mkview">:mkview</a> 
命令来储存和还原折叠状态。

标志折叠法要求你修改文件。如果你与它人共享这个文件，或不得不遵守公司规定的标
准，那么你也许得不到许可给文件加标志。
   标志折叠的主要优点是，你可以精确的把标志放在你要的位置。那样就避免了那种在
你剪切和粘贴折叠时漏了几行文本的情况。并且，你还可以加个注释，说明该折叠包含些
什么。

缩进折叠法是那种在许多文件里都用的着。但并不是每次都能成功的方法。当你无法采用
其它方法时，就用这种。然而，缩进折叠在做提纲时特别有用。你必须为每一层嵌套折叠
特意的使用同一缩进宽度 <a href="options.html#'shiftwidth'">'shiftwidth'</a>。

表达式折叠法能够在几乎任何有结构特定的文本中创建折叠。这种方法相当简单，尤其当
折叠的开始和结束处能容易地被识别的时候。
   如果你用 "expr" 方法来定义折叠而无法得到完全满意的结果。那么你可以切换到手
动方法 "manual"。这么做不会删除那些已经定义好了的折叠。之后你便可以手动删除或
增加折叠了。

</section><hr class="doubleline" /><section class=inner>
<h4></h4>下一章:  <a href="usr_29.html#usr_29.txt">usr_29.txt</a>   在代码间移动

版权: 参见  <a href="usr_01.html#manual-copyright">manual-copyright</a>   vim:tw=78:ts=8:noet:ft=help:norl:
</section>
</article>
<footer>
Generated by vim2html
</footer>
</body>
</html>
